const { throttle } = require('underscore');
const { eventHub } = require('../../models/event-hub');
const logger = require('../../models/logger');
const publisher = require('../../models/redis/publisher');
const utility = require('../../models/utility');

function progressNotify(stages = [
  { name: 'upload', scale: 0.3 },
  { name: 'uncompress', scale: 0.4 },
  { name: 'database', scale: 0.3 },
]) {
  return (req, res, next) => {
    const chan = utility.getSessionId();
    // todo: redis client automaticly subscribe/unsubscribe
    if (chan) {
      const publish = publisher.publishProgressMessage;
      const publishThrottled = throttle(publish, 500, {
        // disable the execution on the trailing-edge
        // 保证推送出去的进度都是当前时刻的进度，不是当前时刻的进度会被丢弃
        // 同时大概率会造成最后一条进度消息被丢弃，所以100%进度消息在当前request的close回调中补发
        trailing: false,
      });
      const stagesMap = {};
      stages.reduce((cnt, stage) => {
        const start = cnt;
        cnt += stage.scale;
        stagesMap[stage.name] = {
          scale: stage.scale,
          start,
        };
        return cnt;
      }, 0);
      let currentStage;
      eventHub.on(chan, (stage, progress) => {
        currentStage = stage;
        const { scale, start } = stagesMap[stage];
        progress = parseInt((start + progress * scale) * 10000, 10) / 10000;
        logger.verbose(chan, stage, progress);
        publishThrottled('update', {
          progress,
          stage,
        });
      });
      res.on('close', () => {
        // 请求结束
        logger.verbose('请求结束...');
        publish('update', {
          progress: 1,
          stage: currentStage,
        });
        // 移除监听
        eventHub.removeListenersByEvent(chan);
      });
    }
    next();
  };
}

module.exports = progressNotify;
